#ifndef _SCN_H
#define _SCN_H

#if C2504
#pragma message("Scene.h")
#endif

#include "D3D11Client.h"
#include "D3D11Effect.h"
#include "PostProcessingPipeline.h"

class D3D11Client;
class vObject;
class vStar;
class vPlanet;
class vVessel;
class vBase;
class D3D11ParticleStream;

class CelBackground;
class CelSphere;

struct CELOBJ {
	vObject *vo;
	double cdist;
	int type;
};

struct DISPLAY_TEXTURE_VERTEX
{
	float x, y, z, w;
	float tu, tv;
};

//local light source
struct D3D11Light {
	D3DXVECTOR4 ambient;	//16
	D3DXVECTOR3 diffuse;
	float Range;			//32
	D3DXVECTOR3 specular;
	float Falloff;			//48
	D3DXVECTOR3 PosW;
	float Theta;			//64
	D3DXVECTOR3 DirW;
	float Phi;				//80
	D3DXVECTOR3 Att;
	UINT32 Type;			//96
};

struct LIGHTLIST {
	const LightEmitter *em;
	vVessel *vobj;
	double camdist2;
};

class Scene {
	friend class D3D11Client;
	friend class D3D11Pad;

	friend class D3D11Mesh;
	friend class vObject;
	friend class TextureMgr;
	friend class Overlay;
	friend class vPlanet;
public:
//init:
	Scene( D3D11Client *_gc, D3D11Config *_cfg );
	~Scene();
	void Init3D();
	void InitStatics();
	void InitObjects();
	void Exit3D();

//vessels:
	//particle streams
	void AddParticleStream( D3D11ParticleStream *ps );
	void DeleteParticleStream( D3D11ParticleStream *ps );

	vVessel *GetVessel( OBJHANDLE obj );
	vPlanet *GetPlanet( OBJHANDLE obj );
	//add/delete
	void NewVessel( OBJHANDLE obj );
	void DeleteVessel( OBJHANDLE obj );
		
//matrixes:
	D3DXMATRIX *GetVP()		{	return &ViewProj;	}
	D3DXMATRIX *GetVP_VC()	{	return &ViewProj_VC;	}
	D3DXMATRIX *GetV()		{	return &View;		}
	D3DXMATRIX *GetP()		{	return &Proj;		}
	UINT GetLocalLightCount()		{	return nLights;	}
	D3D11Light *GetLocalLights()	{	return LL;		}
//VC:
	VCMFDSPEC *GetMFDSpec()	{	return specMFD;		}
	VCHUDSPEC *GetHUDSpec()	{	return &specHUD;	}
	Texture	**GetMFDTex()	{	return texMFD;		}
	Texture **GetHUDTex()	{	return &texHUD;		}
//misc:
	double GetCamAperture()	{	return CamAperture;	}
	float GetAspect()		{	return Aspect;		}
	OBJHANDLE GetProxyBody(){	return Proxy;		}
	VECTOR3 GetCamPos() const		{	return CamPos_new;		}
	float GetFarPlane()		{	return far_plane;	}
	DWORD GetBgColor()		{	return bg_rgba;		}
	D3DXVECTOR3 *GetAmbientColor()	{	return &cBackground;	}
	DWORD GetPlanetariumFlag()	{	return PlanetariumFlag;	}

	TextureMgr * GetTextureMgr();
	inline D3D11Client * GetClient() { return _gc; }

	float GetLuminance();

//rendering:
	void Render_0();
	void SaveParams();
	void RenderVesselShadows( vPlanet *PLN );
	void Render_1();
	void Update();
	void RenderOverlay( SURFHANDLE *surf, MESHHANDLE Mesh, MATRIX3 *T, bool transparent );

//checks visibility of a bounding sphere
	float vh, vw;
	float vhf, vwf;
	D3DXVECTOR3 camera_x;
	D3DXVECTOR3 camera_y;
	D3DXVECTOR3 camera_z;
	bool IsVisibleInCamera( D3DXVECTOR3 *vec, float rad );
	bool IsVisiblePoint( D3DXVECTOR3 *vec );

	ATM_FOG_PARAMS *GetAtmParams()			{	return APRM;	}
	void SetAtmParams( ATM_FOG_PARAMS *in )	{	APRM = in;		}

	void SetRenderTarget();
	void Render3DCompleted();

	const D3DXMATRIX& GetShadowVPMatrix() const;
	const D3DXMATRIX *GetShadowViewMatrix( BYTE cascade );
private:
	D3D11Client *_gc;

	void AddLocalLight( const LightEmitter *em, vVessel *vobj, D3D11Light *L );
	void UpdateSkyColor();
	void RenderObjectMarker( VECTOR3 *dir, char *label0, char *label1, int mode, int scale );

//	void ResizeBuffers();
	void InitGlobalVars();
	void DeleteGlobalVars();

	DWORD BBDrawCount;

//managers:
	CelBackground *CB;
	CelSphere *CS;

//loaded objects:
//==================
//Planets and stars:
	struct GBODY {
		vObject *vobj;
		int type;
	} *GObject;
	DWORD GObjCount;
	CELOBJ PLIST[MAXPLANET];

//Vessels:
	vVessel **Vessel;
	DWORD VesselCount;
	vVessel *vFocus;
	bool bCockpit, bVC, bPause, bPause_new;
	VCHUDSPEC specHUD;
	VCMFDSPEC specMFD[MAXMFD];
	Texture *texHUD, *texMFD[MAXMFD];

	D3D11ParticleStream **PStream;
	DWORD nstream;

//texture buffers:
	IDXGISurface1
		*PBuffer_Surf;
	ID3D11Texture2D
		*BackBuffer,
		*RTarget,
		*PBuffer;
	ID3D11RenderTargetView
		*BackBuffer_RTV,
		*RTarget_RTV,
		*PBuffer_RTV;
	ID3D11ShaderResourceView
		*RTarget_SRV,
		*PBuffer_SRV;
	ID3D11DepthStencilView
		*RTarget_DSV;
//states:
//	ID3D11DepthStencilState
//		*DSS_NoDepth_NoStencil;		//planets, stars, markers, 2D, etc.
	//	*DSS_FlatShadows;			//base & vessel shadows
	//	*DSS_Vessels;				//vessels
//vars:
	WORD PBuffers_counter;	//not needed ?
	OBJHANDLE
		Proxy,		//proxy GBody [current frame]
		Proxy_new;	//proxy GBody [new frame]
	float
		Aspect,		//width/heigth of window
		near_plane,	//camera's near plane [1.0 def]
		far_plane;	//camera's far plane [1e6 def]
	double
		CamAperture,
		CamAperture_new;			//obtained through oapiCameraAperture()
	D3DXMATRIX
		ViewProj_VC, ViewProj_VC_new,
		View, Proj, ViewProj,
		View_new, Proj_new, ViewProj_new;
	VECTOR3
		CamPos,		//[current frame]
		CamPos_new;	//[next frame]
	D3DXVECTOR3	cBackground;//sky color float4
	DWORD bg_rgba;			//sky color DWORD
	double	dSkyBrt;		//sky brightness
	int BgLvl;				//background level
	DWORD PlanetariumFlag;	//current planetarium mode

	ATM_FOG_PARAMS *APRM;	//atmospere params for proxy body

	//2D Sketchpad
	D3D11Pad *pSketch;
	COLORREF LabelCol[6];
	oapi::Pen
		*LabelPen[6],
		*NullPen;
	oapi::Font
		*LabelFont,
		*DebugFont;
	oapi::Brush
		*DebugBrush;

	//debug string
	char debug_str[256];
	int debug_len;

	//local lights
	D3D11Light *LL;
	LIGHTLIST *LList;				//array of nearest local lights
	DWORD nLights, maxlight;	//max local lights
	bool bLocalLights;			//LL enabled

	//HDR-related stuff
	bool enableHDR;

	std::unique_ptr<PostProcessingPipeline> m_ppPipeline;

	bool InitHDRResources();

	CComPtrEx<ID3D11Texture2D>				HDRTarget;
	CComPtrEx<ID3D11Texture2D>				HDRTarget_resolved;
	CComPtrEx<ID3D11RenderTargetView>		HDRTarget_RTV;	
	
	CComPtrEx<ID3D11Texture2D>				m_PPResult;
	CComPtrEx<ID3D11ShaderResourceView>		m_PPResult_SRV;
	
	CComPtrEx<ID3D11PixelShader>			displayTexturePS;
	CComPtrEx<ID3D11VertexShader>			displayTextureVS;
	CComPtrEx<ID3D11InputLayout>			displayTextureLayout;
	CComPtrEx<ID3D11Buffer>					displayTextureVB;
	CComPtrEx<ID3D11Buffer>					displayTextureIB;

	//---------------- shadow maps ------------

	int mainShadowMapSize;

	D3DXMATRIX shadowView[4], shadowProj, shadowVP[4];
	D3DXVECTOR3 sunDirection, shadowReferencePoint;

	bool InitShadowMap();
	void CalcShadowMapMatrices();

	CComPtrEx<ID3D11Texture2D>				mainShadowMap;
	CComPtrEx<ID3D11DepthStencilView>		mainShadowMap_DSV;
	CComPtrEx<ID3D11ShaderResourceView>		mainShadowMap_SRV;

	CComPtrEx<ID3D11SamplerState>			ssMainShadowMap;

	CComPtrEx<ID3D11RasterizerState>		mainShadowMapRS;
	CComPtrEx<ID3D11DepthStencilState>		mainShadowMapDSS;
};

#endif
